package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.RedisConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishAddDTO;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.BaseException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.service.SetmealService;
import com.sky.vo.DishPageQueryItemVO;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper flavorMapper;

    @Autowired
    private SetmealService setmealService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 问题
    //1. 事务问题
    //2. 性能问题
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(DishAddDTO dto) {
        // 新增dish
        Dish dish = new Dish();
        BeanUtils.copyProperties(dto, dish);
        dishMapper.insert(dish);
        // 新增dish_flavor
        List<DishFlavor> flavors = dto.getFlavors();
        if(!CollectionUtils.isEmpty(flavors)){
            for (DishFlavor flavor : flavors) {
                // 需要在insert dish的时候 获取自增的id
                flavor.setDishId(dish.getId());
                // flavorMapper.insert(flavor);
            }
            // 为了提升性能,批量插入,而不是for循环单条插入
            flavorMapper.insertBatch(flavors);
        }
        // 删除dish的缓存
        deleteCache(dto.getCategoryId());
    }

    @Override
    public PageResult<DishPageQueryItemVO> page(DishPageQueryDTO dto) {
        //开启分页
        PageHelper.startPage(dto.getPage(), dto.getPageSize());
        // 关联查询,查dish和category
        Page<DishPageQueryItemVO> page = dishMapper.page(dto);
        // 封装返回
        return new PageResult(page.getTotal(), page.getResult());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return;
        }
        for (Long id : ids) {
            // 根据id查菜品
            Dish dish = dishMapper.selectById(id);
            if(dish == null){
                log.error("菜品不存在,id:{}", id);
                throw new BaseException(MessageConstant.DISH_NOT_EXIST);
            }
            // 判断是否在售,如果在售,抛异常结束
            if(Objects.equals(dish.getStatus(), StatusConstant.ENABLE)){
                throw new BaseException(MessageConstant.DISH_ON_SALE);
            }
            // 判断是否关联了套餐， 查询包含dishId的状态是启用的套餐的数量
            int count = setmealService.countEnableByDishId(id);
            // 如果关联了,抛异常结束
            if(count > 0){
                throw new BaseException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
            }
            // 删除菜品
            dishMapper.deleteById(id);
            // 删除口味
            flavorMapper.deleteByDishId(id);
            // 删除缓存
            deleteCache(dish.getCategoryId());
        }


    }

    @Override
    public DishVO getById(Long id) {
        // 方法1: 2条sql 分别查dish和dish_flavor,然后拼装
        // 先去根据id查dish
        Dish dish = dishMapper.selectById(id);
        if(dish == null){
            log.error("菜品不存在,id:{}", id);
            throw new BaseException(MessageConstant.DISH_NOT_EXIST);
        }
        // 根据dish_id查询flavor
        List<DishFlavor> flavors = flavorMapper.selectByDishId(id);
        // 组合起来
        DishVO vo = new DishVO();
        // 填充dish数据
        BeanUtils.copyProperties(dish, vo);
        // 填充口味数据
        vo.setFlavors(flavors);
        return vo;
        // 方法2:关联查询, 使用<collection>标签映射结果集
        //return dishMapper.selectByIdWithFlavors(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DishDTO dto) {
        // 更新dish
        Dish dish = new Dish();
        BeanUtils.copyProperties(dto, dish);
        dishMapper.update(dish);
        // 删除dish_flavor
        flavorMapper.deleteByDishId(dto.getId());
        // 重新insert flavor
        List<DishFlavor> flavors = dto.getFlavors();
        // 防止空指针
        if(!CollectionUtils.isEmpty(flavors)){
            // stream流
            flavors.forEach(f->f.setDishId(dto.getId()));
            // 批量插入
            flavorMapper.insertBatch(flavors);
        }
        // 删除缓存
        deleteCache(dish.getCategoryId());
    }

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    @Override
    public List<Dish> list(Long categoryId) {
        Dish dish = Dish.builder()
                .categoryId(categoryId)
                .status(StatusConstant.ENABLE)
                .build();
        return dishMapper.list(dish);
    }

    @Override
    public void enableOrDisable(Long id, Integer status) {
        // 关联了套餐的不能停售
        if(Objects.equals(status, StatusConstant.DISABLE)){
            int count = setmealService.countEnableByDishId(id);
            if(count > 0){
                throw new BaseException(MessageConstant.DISH_STOP_BE_RELATED_BY_SETMEAL);
            }
        }
        // 查询数据库，获取分类id
        DishVO dishVo = this.getById(id);
        if(dishVo == null){
            throw new BaseException(MessageConstant.DISH_NOT_EXIST);
        }

        // 修改
        Dish dish = new Dish();
        dish.setId(id);
        dish.setStatus(status);
        dishMapper.update(dish);
        // 删除缓存
        deleteCache(dishVo.getCategoryId());
    }

    private void deleteCache(Long categoryId){
        String key = RedisConstant.KEY_PREFIX + "categoryId:"+categoryId;
        stringRedisTemplate.delete(key);
    }

    //前缀： 部门:开发组:模块:业务key
    @Override
    public List<DishVO> listWithFlavor(Long categoryId) {
        String key = RedisConstant.KEY_PREFIX + "categoryId:"+categoryId;
        // 查询redis
        String json = stringRedisTemplate.opsForValue().get(key);
        // redis有 直接返回
        if(StringUtils.hasLength(json)){
            // json转list
            List<DishVO> dishVOList = JSON.parseArray(json, DishVO.class);
            return dishVOList;
        }
        // redis没有，查询数据库
        // 查询菜品列表
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);
        List<Dish> dishList = dishMapper.list(dish);
        List<DishVO> dishVOList = new ArrayList<>();
        // 遍历菜品，查询口味
        for (Dish d : dishList) {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(d,dishVO);
            //根据菜品id查询对应的口味
            List<DishFlavor> flavors = flavorMapper.selectByDishId(d.getId());
            dishVO.setFlavors(flavors);
            dishVOList.add(dishVO);
        }
        // 数据库不空，写入redis
        if(!CollectionUtils.isEmpty(dishVOList)){
            stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(dishVOList));
        }
        return dishVOList;
    }
}
